package tianhao.luo.recursion;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 迷宫
 *
 * @author: tianhao.luo@hand-china.com 2021/6/16  14:36
 */
public class Maze {


    private final int[][] map = new int[8][7];
    private final int rowLength;
    private final int columnLength;


    public Maze() {

        System.out.println("地图初始化完毕....");
    }

    {
        System.out.println("地图初始化中......");

        // 将地图四周元素置为1,表示无法越过
        this.rowLength = map.length;
        this.columnLength = map[0].length;
        // 竖向的墙
        for (int i = 0; i < rowLength; i++) {
            map[i][0] = 1;
            map[i][columnLength - 1] = 1;
        }

        // 横向的墙
        for (int i = 0; i < columnLength; i++) {
            map[0][i] = 1;
            map[rowLength - 1][i] = 1;
        }

        // 设置两个挡板
        map[3][1] = 1;
        map[3][2] = 1;

        // 全部封闭
//        map[1][2] = 1;
//        map[2][2] = 1;

        for (int i = 0; i < rowLength; i++) {
            for (int j = 0; j < columnLength; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }

    }

    /**
     * 在默认地图中,从起始位置开始,找到能走到最右下角的通路
     * <p>
     * i,j表示起始位置
     * map[rowLength-1][columnLength-1] 节点找到时,表示已经找到通路
     * 约定:当map[i][j]为0表示该点没有走过,当为1表示遇到墙,2表示是通路可以走,3表示该点走过,但走不通
     *
     * @param i 起始位置横向索引
     * @param j 起始位置竖向索引
     * @return 找到通路返回true, 否则返回false
     */
    public boolean setWay(int i, int j) {
        // 定义退出递归的条件
        if (map[rowLength - 2][columnLength - 2] == 2) {
            System.out.println("=====>最终map");
            printMap();
            return true;
        } else {
            // 当前节点是没有走过的,才可以进行找路操作
            if (map[i][j] == 0) {
                // 假设当前节点可以走通
                map[i][j] = 2;
                // 我们自定义找路策略: 下->右->上->左
                if (setWay(i + 1, j)) {
                    System.out.println("=====>向下走成功map[" + i + "][" + j + "]=" + map[i][j]);
                    return true;
                } else if (setWay(i, j + 1)) {
                    System.out.println("=====>向右走成功map[" + i + "][" + j + "]=" + map[i][j]);
                    return true;
                } else if (setWay(i - 1, j)) {
                    System.out.println("=====>向上走成功map[" + i + "][" + j + "]=" + map[i][j]);
                    return true;
                } else if (setWay(i, j - 1)) {
                    System.out.println("=====>向左走成功map[" + i + "][" + j + "]=" + map[i][j]);
                    return true;
                } else {
                    // 四个方向都走不通,表示无路可走
                    map[i][j] = 3;
                    System.out.println("=====>map[" + i + "][" + j + "]=" + map[i][j] + "四个方向都走不通的map");
                    return false;
                }
            } else {
                // 如果这个节点不为0,则表示不能走
                // 为什么下面这段输出是在找路过程中最先输出?先要理解下面两个问题
                // 1.什么情况下会进入这段逻辑?===>当探测的节点值不为0时
                // 2.else内的代码有继续递归吗?====>没有继续递归
                // 没有递归,表示走完输出,就已经结束了这次的方法调用了;其他的继续探测的还是会继续执行
                // 按照我们默认的探测策略:下->右->上->左,最先探测到的节点值不为0时,就会输出下面的内容
                System.out.println("=====>节点map[" + i + "][" + j + "]=" + map[i][j] + "不为0的map");
                return false;
            }
        }
    }

    public void printMap() {
        for (int i = 0; i < rowLength; i++) {
            for (int j = 0; j < columnLength; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }

//    public static Strategy[][] createStrategy() {
//        // 默认只支持 上下左右四个方向
//        // 创建的策略是这4中的排列组合
//        Strategy[][] strategy = new Strategy[24][4];
//        List<Strategy> strategyList = new ArrayList<>();
//        strategyList.add(Strategy.on);
//        strategyList.add(Strategy.down);
//        strategyList.add(Strategy.left);
//        strategyList.add(Strategy.right);
//        // 1.从四种策略中选择一种
//        int count = 0;
//        for (Strategy one : strategyList) {
//            List<Strategy> collect = strategyList.stream().filter(integer -> !one.equals(integer)).collect(Collectors.toList());
//            count++;
//            for (Strategy two : collect) {
//                List<Strategy> collect2 = collect.stream().filter(integer -> !two.equals(integer)).collect(Collectors.toList());
//                count++;
//                for (Strategy three : collect2) {
//                    List<Strategy> collect3 = collect2.stream().filter(integer -> !three.equals(integer)).collect(Collectors.toList());
//                    count++;
//                    for (Strategy four : collect3) {
//                        count++;
//                        strategy[count / 4][0] = one;
//                        strategy[count / 4][1] = two;
//                        strategy[count / 4][2] = three;
//                        strategy[count / 4][3] = four;
//                    }
//                }
//            }
//        }
//        return strategy;
//    }
//
//
//    public int count2(){
//        int count =0;
//        for (int i = 0; i < rowLength; i++) {
//            for (int j = 0; j < columnLength; j++) {
//                if (map[i][j] == 2){
//                    count++;
//                }
//            }
//        }
//        return count;
//    }
//
//
//    public boolean setWay2(int i, int j, Strategy[] strategy) {
//        // 定义退出递归的条件
//        if (map[rowLength - 2][columnLength - 2] == 2) {
//            System.out.println("=====>最终map");
//            printMap();
//            return true;
//        } else {
//            // 当前节点是没有走过的,才可以进行找路操作
//            if (map[i][j] == 0) {
//                // 假设当前节点可以走通
//                map[i][j] = 2;
//                // 我们自定义找路策略: 下->右->上->左
//                // 使用自动创建的策略
//                if ((strategy[0] == Strategy.on) && setWay2(i - 1, j, strategy)) {
//                    System.out.println("=====>向上走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[0] == Strategy.down) && setWay2(i + 1, j, strategy)) {
//                    System.out.println("=====>向下走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[0] == Strategy.right) && setWay2(i, j + 1, strategy)) {
//                    System.out.println("=====>向右走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[0] == Strategy.left) && setWay2(i, j - 1, strategy)) {
//                    System.out.println("=====>向左走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                }else if ((strategy[1] == Strategy.on) && setWay2(i - 1, j, strategy)) {
//                    System.out.println("=====>向上走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[1] == Strategy.down) && setWay2(i + 1, j, strategy)) {
//                    System.out.println("=====>向下走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[1] == Strategy.right) && setWay2(i, j + 1, strategy)) {
//                    System.out.println("=====>向右走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[1] == Strategy.left) && setWay2(i, j - 1, strategy)) {
//                    System.out.println("=====>向左走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[2] == Strategy.on) && setWay2(i - 1, j, strategy)) {
//                    System.out.println("=====>向上走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[2] == Strategy.down) && setWay2(i + 1, j, strategy)) {
//                    System.out.println("=====>向下走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[2] == Strategy.right) && setWay2(i, j + 1, strategy)) {
//                    System.out.println("=====>向右走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[2] == Strategy.left) && setWay2(i, j - 1, strategy)) {
//                    System.out.println("=====>向左走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                }else if ((strategy[3] == Strategy.on) && setWay2(i - 1, j, strategy)) {
//                    System.out.println("=====>向上走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[3] == Strategy.down) && setWay2(i + 1, j, strategy)) {
//                    System.out.println("=====>向下走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[3] == Strategy.right) && setWay2(i, j + 1, strategy)) {
//                    System.out.println("=====>向右走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                } else if ((strategy[3] == Strategy.left) && setWay2(i, j - 1, strategy)) {
//                    System.out.println("=====>向左走成功map[" + i + "][" + j + "]=" + map[i][j]);
//                    return true;
//                }
//
//                else {
//                    // 四个方向都走不通,表示无路可走
//                    map[i][j] = 3;
//                    System.out.println("=====>map[" + i + "][" + j + "]=" + map[i][j] + "四个方向都走不通的map");
//                    return false;
//                }
//
//            } else {
//                // 如果这个节点不为0,则表示不能走
//                // 为什么下面这段输出是在找路过程中最先输出?先要理解下面两个问题
//                // 1.什么情况下会进入这段逻辑?===>当探测的节点值不为0时
//                // 2.else内的代码有继续递归吗?====>没有继续递归
//                // 没有递归,表示走完输出,就已经结束了这次的方法调用了;其他的继续探测的还是会继续执行
//                // 按照我们默认的探测策略:下->右->上->左,最先探测到的节点值不为0时,就会输出下面的内容
//                System.out.println("=====>节点map[" + i + "][" + j + "]=" + map[i][j] + "不为0的map");
//                return false;
//            }
//        }
//    }
//
//    enum Strategy {
//
//        on(1),
//        down(2),
//        left(3),
//        right(4);
//
//        private int direction;
//
//        Strategy(int direction) {
//            this.direction = direction;
//        }
//
//        public int getDirection() {
//            return direction;
//        }
//    }
}

